package com.lcy.mybatis.generator.plugin;

import com.lcy.mybatis.generator.plugin.element.*;
import org.apache.ibatis.annotations.Param;
import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.xml.Document;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

/**
 * SimpleSqlPlugin
 * 自动生成代码时，加入几个常用方法：
 * 1、select * from table where column = value
 * 2、select * from table where column1 = value1 and column2 = value2
 * 3、select count(*) from table where column = value
 * 4、select count(*) from table where column1 = value1 and column2 = value2
 *
 * <p>创建时间：2017/5/4 16:05</p>
 *
 * @author 娄存银
 * @version 1.0
 */
public class SimpleSqlPlugin extends PluginAdapter {

    // Mapper 添加自定义方法
    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        interfaze.addImportedType(new FullyQualifiedJavaType(Param.class.getName()));
        for (CustomerSqlElement element :getElements(introspectedTable)) {
            interfaze.addMethod(element.getMethod());
            interfaze.addImportedTypes(element.getImports());
        }
        return true;
    }

    // Mapper 添加自定义 SQL
    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        XmlElement parentElement = document.getRootElement();
        for (CustomerSqlElement element :getElements(introspectedTable)) {
            parentElement.addElement(element.getXmlElement());
        }
        return true;
    }


    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        generateConstColumnFiled(introspectedTable,topLevelClass);
        generateContainsColumn(introspectedTable,topLevelClass);
        return true;
    }

    // 插入的内容集合
    private List<CustomerSqlElement> getElements(IntrospectedTable table){
        List<CustomerSqlElement> elements = new ArrayList<>();
        elements.add(new SelectAllElement(table));
        elements.add(new SelectByColumnElement(table));
        elements.add(new SelectFirstByColumnElement(table));
        elements.add(new SelectByColumnsElement(table));
        elements.add(new SelectFirstByColumnsElement(table));
        elements.add(new TotalCountElement(table));
        elements.add(new CountByColumnElement(table));
        elements.add(new CountByColumnsElement(table));
        elements.add(new DeleteByColumnElement(table));
        elements.add(new DeleteByColumnsElement(table));
        return elements;
    }


    public boolean validate(List<String> warnings) {
        return true;
    }

    private void generateContainsColumn(IntrospectedTable introspectedTable, TopLevelClass topLevelClass){
        Method method = new Method("contains");
        method.setReturnType(new FullyQualifiedJavaType("boolean"));
        method.setVisibility(JavaVisibility.PUBLIC);
        method.setStatic(true);
        Parameter parameter = new Parameter(new FullyQualifiedJavaType("String"),"value");
        method.addParameter(parameter);
        String content = "if(value == null){\n" +
                "            return false;\n" +
                "        }\n" +
                "        for (String column:COLUMNS) {\n" +
                "            if(column.equals(value)){\n" +
                "                return true;\n" +
                "            }\n" +
                "        }\n" +
                "        return false;";
        method.addBodyLine(content);
        topLevelClass.addMethod(method);
    }

    private void generateConstColumnFiled(IntrospectedTable introspectedTable, TopLevelClass topLevelClass){
        List<IntrospectedColumn> columns = introspectedTable.getAllColumns();
        StringBuilder builder = new StringBuilder();
        builder.append("{");
        for (IntrospectedColumn introspectedColumn:columns) {
            String name = introspectedColumn.getActualColumnName().toUpperCase();
            Field field1 = new Field(name,new FullyQualifiedJavaType("String"));
            field1.setFinal(true);
            field1.setStatic(true);
            field1.setInitializationString(String.format("\"%s\"",introspectedColumn.getActualColumnName()));
            field1.setVisibility(JavaVisibility.PUBLIC);
            topLevelClass.addField(field1);
            builder.append(name)
                    .append(",");
        }
        builder.deleteCharAt(builder.length()-1);
        builder.append("}");
        Field allColumn = new Field("COLUMNS",new FullyQualifiedJavaType("String[]"));
        allColumn.setVisibility(JavaVisibility.PUBLIC);
        allColumn.setFinal(true);
        allColumn.setStatic(true);
        allColumn.setInitializationString(builder.toString());
        topLevelClass.addField(allColumn);

    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        try {
            java.lang.reflect.Field field = sqlMap.getClass().getDeclaredField("isMergeable");
            field.setAccessible(true);
            field.setBoolean(sqlMap, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}
